<template>
  <div class="qr-code" v-loading="loading" :style="{width:`${width}px`,height:`${height}px`,padding:`${padding}px`}">
    <div class="qr-error login-tips" v-if="!hasLogin">
      <el-button size="small" type="primary" @click="$emit('login')">请先登录</el-button>
    </div>
    <div class="qr-error login-tips" v-else-if="!isAgree">
      <el-button size="small" type="primary" @click="$emit('update:isAgree',true)">确认协议并支付</el-button>
    </div>
    <div class="code-box"
      v-show="hasLogin&&isAgree">
      <!-- <div
        ref="qrCode"
        key="code">
      </div> -->
      <div class="qrcode"
        ref="qrcode"
        v-show="!error">
        <img :src="qrCodeImg">
      </div>
      <div v-show="error||confirmTips"
        class="refresh qr-error"
        key="refresh"
        @click="refreshCode">
        <div v-if="error">
          <svg-icon icon-class="code-refresh" />
          <p class="text-error">{{error}}</p>
        </div>
        <div class="confirm-tips" v-else v-html="confirmTips"></div>
      </div>
    </div>
  </div>
</template>
<script>
import { getParams, debounce } from '@/utils'
import QRCode from 'qrcodejs2'
import { getPrepayCode, checkCodeStatus, checkCodeFinish } from './api'
export default {
  name: 'PaymentCode',
  props: {
    isAgree: {
      type: Boolean,
      default: true
    },
    hasLogin: {
      type: Boolean,
      default: false
    },
    product: {
      type: Object,
      require: true
    },
    logo: String,
    otherParamsStr: {
      type: String,
      default: '{}'
    },
    width: {
      type: Number,
      default: 150
    },
    height: {
      type: Number,
      default: 150
    },
    padding: {
      type: Number,
      default: 10
    }
  },
  data () {
    return {
      isOnShow: true,
      loading: false,
      qrcode: null,
      timer: null,
      validMinute: '10',
      error: '',
      confirmTips: '',
      times: 600,
      qrCodeImg: ''
    }
  },
  watch: {
    'product.id': {
      handler () {
        if (this.getPrepayCodeInfo_) {
          this.getPrepayCodeInfo_()
        } else {
          this.getPrepayCodeInfo()
        }
      },
      immediate: true
    },
    otherParamsStr (val) {
      this.getPrepayCodeInfo_()
    },
    'hasLogin' () {
      this.getPrepayCodeInfo_()
    },
    isAgree () {
      this.qrCodeImg = ''
      this.getPrepayCodeInfo_()
    }
  },
  created () {
    this.getPrepayCodeInfo_ = debounce(() => {
      this.getPrepayCodeInfo()
    }, 250, false)
  },
  mounted () {
    // const container = this.$refs.qrCode
    // this.qrcode = new QRCode(container, {
    //   text: this.text,
    //   width: this.width - this.padding * 2,
    //   height: this.height - this.padding * 2,
    //   colorDark: '#000000',
    //   colorLight: '#ffffff',
    //   correctLevel: 0
    // })
  },
  activated () {
    this.isOnShow = true
    this.getPrepayCodeInfo()
  },
  deactivated () {
    this.isOnShow = false
    this.getPrepayCodeInfo()
  },
  beforeDestroy () {
    this.isOnShow = false
    this.getPrepayCodeInfo()
  },
  methods: {
    refreshCode () {
      this.$emit('refresh')
      this.getPrepayCodeInfo()
    },
    getInstance (w, h) {
      if (this.instance) return this.instance
      const div = document.createElement('div')
      this.instance = new QRCode(div, {
        text: '',
        render: 'canvas',
        width: w,
        height: h,
        colorDark: '#000000',
        colorLight: '#ffffff',
        correctLevel: QRCode.CorrectLevel.Q
      })
      return this.instance
    },
    setQrcode (url) {
      const h = this.width - this.padding * 2
      const w = this.height - this.padding * 2
      const instance = this.getInstance(h, w)
      instance.makeCode(url)
      const canvas = instance._oDrawing._elCanvas
      const ctx = canvas.getContext('2d')
      const image = new Image()
      image.src = require(`@/assets/${this.logo}.png`)
      image.onload = () => {
        const imgW = this.width < 150 ? 20 : 28
        const imgH = this.height < 150 ? 20 : 28
        const padding = 3
        const bgw = imgW + padding * 2
        const bgh = imgH + padding * 2
        const bgx = (w - bgw) / 2
        const bgy = (h - bgh) / 2
        // 画logo后面白色背景图
        this.drawArcBackground(ctx, bgx, bgy, bgw, bgh, 0)

        // 画logo
        const logx = (w - imgW) / 2
        const logy = (h - imgH) / 2
        ctx.drawImage(image, logx, logy, imgW, imgH)
        this.loading = false
        this.qrCodeImg = canvas.toDataURL('image/png')
      }
    },
    // 画正方形背景
    drawArcBackground (ctx, x, y, w, h, r) {
      ctx.beginPath()
      ctx.moveTo(x + r, y)
      ctx.lineTo(x + w - r, y)
      ctx.arc(x + w - r, y + r, r, Math.PI * 1.5, Math.PI * 2)
      ctx.lineTo(x + w, y + h - r)
      ctx.arc(x + w - r, y + h - r, r, 0, Math.PI * 0.5)
      ctx.lineTo(x + r, y + h)
      ctx.arc(x + r, y + h - r, r, Math.PI * 0.5, Math.PI)
      ctx.lineTo(x, y + r)
      ctx.arc(x + r, y + r, r, Math.PI, Math.PI * 1.5)
      ctx.closePath()

      ctx.fillStyle = '#fff'
      ctx.fill()
    },
    setTime (oldCode) {
      clearTimeout(this.timer)
      this.timer = setTimeout(() => {
        if (!this.qrCode || this.error || oldCode !== this.qrCode) return
        oldCode = this.qrCode
        checkCodeStatus({ qr_code: this.qrCode }).then(res => {
          if (oldCode !== this.qrCode) return
          const data = res.data || {}
          if (data.expire < 1) {
            this.error = '支付超时!'
            this.$emit('onStatusChange', 'timeout')
          } else if (data.status === 1) {
            this.confirmTips = '已扫码<br/>未完成付款前<br/>请勿刷新当前二维码'
          } else if (data.status === 0) {
            this.getPrepayCodeInfo()
            this.$emit('onStatusChange', 'succes')
          } else if (data.status === 2) {
            this.error = '订单无效！'
            this.$emit('onStatusChange', 'error')
          }
          this.setTime(oldCode)
        }).catch(() => {
          if (this.times <= 0) {
            this.error = '二维码已过期'
          } else {
            this.setTime(oldCode)
          }
          this.times -= 3
        })
      }, 3000)
    },
    getPrepayCodeInfo () {
      clearTimeout(this.timer)
      this.qrCode = null
      this.confirmTips = ''
      if ([!this.isOnShow, !this.hasLogin, !this.isAgree, !this.product.id].includes(true)) return
      // if (!this.isOnShow || !this.hasLogin || !this.product.id) return
      const params = { 'pay_entry': 'web' }
      this.loading = true
      getPrepayCode(params).then(res => {
        this.loading = false
        this.error = ''
        const data = res.data
        this.qrCode = data.qr_code
        this.makePayCode()
        this.validMinute = data.valid_minute || 10
        this.times = data.poll_second || 600
        this.setTime(this.qrCode)
      }).catch((e) => {
        this.error = '请刷新二维码'
        this.loading = false
      })
    },
    makePayCode () {
      // if (this.qrcode) {
      const otherParams = JSON.parse(this.otherParamsStr || '{}')
      const params = Object.assign({
        product: this.product.id,
        codeid: this.qrCode,
        appname: 'xzdesktop',
        wxid: 'wx6d62e451592694f1',
        appid: process.env.VUE_APP_ID
      }, otherParams)

      if (params.noproduct) {
        delete params.noproduct
        delete params.product
      }
      const paramsStr = getParams(params)
      this.setQrcode('https://usercenter-pay.cqttech.com/pay.html?' + paramsStr)
      // this.qrcode._el.title = ''
      // }
    },
    hasPay () {
      if (!this.qrCode) return
      checkCodeFinish({ qr_code: this.qrCode }).then((res) => {
        this.getPrepayCodeInfo()
        this.$emit('onStatusChange', 'succes')
      })
    }
  }
}
</script>
<style lang="scss" scoped>
@import "./index.scss";
</style>
